
import axios from 'axios'
import setConfig from './axios.setConfig.js'
import handleResponse from './axios.handleResponse.js'
import handleError from './axios.handleError.js'
import { againRequest } from './axios.againRequest.js'
import { i18n } from '../../lang'
import { guid, aesEncrypt, aesDecrypt } from './axios.middleware.js'
import { showToast } from 'vant'
import md5 from 'md5'
import baseConfig from '@/config'
import qs from 'qs'
const { t } = i18n.global
/**
 * intactRequest是只在axios基础上更改了请求配置。
 * 而request是基于axios创建的实例，实例只有常见的数据请求方法，没有axios.isCancel/ axios.CancelToken等方法，
 * 也就是没有**取消请求**和**批量请求**的方法。
 * 所以如果需要在实例中调用取消某个请求的方法（例如取消上传），请用intactRequest。
 */
let intactRequest = setConfig(axios)
let request = setConfig(intactRequest.create())

// 请求中的api
let pendingPool = new Map()


/**
 * 请求拦截
 */
const requestInterceptorId = request.interceptors.request.use(
  (config) => {
    let uri = `4cf4c22f6e6ce089937de71339f1b87d`
    // 判断是否加签
    if (baseConfig.isEnableEncryption) {

      let signParam = {
        method: config.method.toUpperCase(), // 请求方法
        uri: `${baseConfig.baseUrl}${config.url}`, // 请求路径 (不清楚这里是否需要全路径) 目前这里的值是 ‘/api/login/xxxx’
        header: config.headers, // 请求头 语言和 token 目前这里的值是 { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Authorization': '1234567890' }
        params: { ...config.data } // 请求参数 因为所有接口都是post 所以这里一定有值
      }
      if(localStorage.getItem('token') != null||localStorage.getItem('token') != undefined){
        console.log(localStorage.getItem('token'),'token');
        
        config.headers['Authorization'] = localStorage.getItem('token')
      }
      let handshake = guid() // 生成一个随机数
      let timestamp = Date.now() // 生成一个时间戳
      let sign = md5(`${signParam}${timestamp}${handshake}`) // 生成一个签名
      let signKey = JSON.stringify(signParam) // 将签名参数转换为字符串

      let encrypData = aesEncrypt(signKey, handshake) // 加密数据
      config.data = {
        handshake,
        timestamp,
        sign,
        data: encrypData
      }
      config.data = qs.stringify(config.data) // 将数据转换为序列化字符串
      config.method = 'post'
      config.url = `${config.baseURL}/api/${uri}` // 将请求路径拼接上url 目前这里的值是 ‘/api/login/xxxx/4cf4c22f6e6ce089937de71339f1b87d’
    }
    return config
  },
  (err) => {
    // 对请求错误做些什么
    return Promise.reject(err)
  }
)
/**
 * 响应拦截
 */
const responseInterceptorId = request.interceptors.response.use(
  (response) => {
    const { data, config } = response
    try {
      if (baseConfig.isEnableEncryption) {
        const cipher = data.data
        const plain = aesDecrypt(cipher, data.handshake)
        try {
          let res = JSON.parse(plain)
          // 如果code不为200，则显示错误信息
          if (res.code != 200) {
            showToast(res.message)
          }
          return Promise.resolve(res)
        } catch (e) {
          console.log(e);

        }
      }


    } catch (e) {
      showToast(e.message)
    }
    // 清理 pending
    if (config && config.__dedupeKey) {
      pendingPool.delete(config.__dedupeKey)
    }
    return Promise.resolve(handleResponse(response))
  },
  // 对异常响应处理
  (err) => {
    const config = err && err.config
    if (!axios.isCancel(err)) {
      if (config && config.__dedupeKey) pendingPool.delete(config.__dedupeKey)
      // 发起重新请求
      return againRequest(err, request)
    }

    if (!err) return Promise.reject(err)

    if (err.response) {
      err = handleError(err)
    }
    // 没有response(没有状态码)的情况
    // eg: 超时；断网；请求重复被取消；主动取消请求；
    else {
      // 错误信息err传入isCancel方法，可以判断请求是否被取消
      if (axios.isCancel(err)) {
        throw new axios.Cancel(err.message || `request '${config && config.url}' cancel`)
      } else if (err.stack && err.stack.includes('timeout')) {
        err.message = t('http.timeout')
      } else {
        err.message = t('http.err')
      }
    }

    showToast(err.message)
    return Promise.reject(err)
  }
)

// 移除全局的请求拦截器
function removeRequestInterceptor() {
  request.interceptors.request.eject(requestInterceptorId)
}

// 移除全局的响应拦截器
function removeResponseInterceptor() {
  request.interceptors.response.eject(responseInterceptorId)
}

/**
 * 清除所有pending状态的请求
 * @param {Array} whiteList 白名单，里面的请求不会被取消
 * 返回值 被取消了的api请求
 */
function clearPendingPool(whiteList = []) {
  if (!pendingPool.size) return

  const pendingUrlList = Array.from(pendingPool.keys()).filter((url) => !whiteList.includes(url))
  if (!pendingUrlList.length) return

  pendingUrlList.forEach((pendingUrl) => {
    // 清除掉所有非全局的pending状态下的请求
    if (!pendingPool.get(pendingUrl).global) {
      pendingPool.get(pendingUrl).cancelFn()
      pendingPool.delete(pendingUrl)
    }
  })

  return pendingUrlList
}

request.removeRequestInterceptor = removeRequestInterceptor
request.removeResponseInterceptor = removeResponseInterceptor
request.clearPendingPool = clearPendingPool

export { intactRequest, request }
